#include "../include/Bullet.h"
#include "../include/Global.h"

#include "SDL/SDL.h"
#include "SDL/SDL_opengl.h"
using namespace std;

//Default Constructor
Bullet::Bullet()
{

    Zpos = GROUND + 2.4;
    Pos = Position(0,0);
    range = 3;
    stepSize = 0.3;
    lastHit = 0;
    minionIndex = 0;
    bulletDamage = 10;
    InitialPos = Position(0,0);
    delay = 2;
    width = 0.1;
    height = 0.1;
    depth = 0.1;
    Timer.start();
    colorR = 0.5;
    colorG = 0.5;
    colorB = 0.5;
    deadMinionIndex = -1;


}

// Draws the bullet at its current location
void Bullet:: draw()
{

    glPushMatrix();
    glPushMatrix();
    glTranslatef(InitialPos.Xpos + Pos.Xpos, InitialPos.Ypos + Pos.Ypos, Zpos);
    glColor3f(colorR, colorG, colorB);
    glLoadName(nBULLET);
    glBegin(GL_QUADS);

//Front
	glNormal3f(0.0f, 0.0f, -1.0f);
	//glNormal3f(-1.0f, 0.0f, -1.0f);
	glVertex3f(-width, -height, -depth);
	//glNormal3f(-1.0f, 0.0f, -1.0f);
	glVertex3f(width, -height, -depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(width, -height, depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(-width, -height, depth);
//Back
	glNormal3f(0.0f, 0.0f, -1.0f);
	//glNormal3f(-1.0f, 0.0f, -1.0f);
	glVertex3f(-width, height, -depth);
	//glNormal3f(-1.0f, 0.0f, -1.0f);
	glVertex3f(width, height, -depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(width, height, depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(-width, height, depth);

	//Top
	glNormal3f(0.0f, 0.5f, 3.0f);
	//glNormal3f(-1.0f, 0.0f, 1.0f);
	glVertex3f(-width, -height, depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(width, -height, depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(width, height, depth);
	//glNormal3f(-1.0f, 0.0f, 1.0f);
	glVertex3f(-width, height, depth);

	//Right
	glNormal3f(1.0f, 0.5f, 0.0f);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(width, -height, -depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(width, height, -depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(width, height, depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(width, -height, depth);




	//Left
	glNormal3f(-1.0f, 0.5f, 0.0f);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(-width, -height, -depth);
	//glNormal3f(1.0f, 0.0f, -1.0f);
	glVertex3f(-width, height, -depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(-width, height, depth);
	//glNormal3f(1.0f, 0.0f, 1.0f);
	glVertex3f(-width, -height, depth);

	glEnd();
    glPopMatrix();
    glPopMatrix();
}

//Sets the initial position of the bullet
void Bullet::setInitialPosition(Position P)
{
    InitialPos = P;
}

//Checks whether or not the delay is up.
bool Bullet :: CheckTimerDelay()
{
    if(Timer.elapsedTime() >= delay)
        return true;
    else
        return false;
}
//Tests whether or not a minion is in range of the bullet
bool Bullet :: TestFire(std::vector<Minion> &min)
{
//Returns the bullet back to its tower if there are no minions left
if(min.size() == 0)
{
    Pos = Position(0,0);
}
    for( int i = 0; i < min.size(); i++)
    {
        if((getDistance(min[i].getPos().Xpos,InitialPos.Xpos, min[i].getPos().Ypos,InitialPos.Ypos) <= range))
        {
           minionIndex = i;
           return true;
        }
    }
    return false;
}


bool Bullet :: TestFire(Position P)
{
//Returns the bullet back to its tower if there are no minions left

    Position Target = P;

        if(getDistance(Target.Xpos,InitialPos.Xpos, Target.Ypos,InitialPos.Ypos) <= range)
           return true;
        else
         return false;
}
//Updates the movement of the bullet to a destination location of a minion,when a minion is struck, then it returns the bullet back
//to its initial posotion.

bool Bullet :: Fire(std::vector<Minion> &min, int i)
{
    double angle = atan(getDistance(0,0,min[i].getPos().Ypos, InitialPos.Ypos)/(getDistance(min[i].getPos().Xpos, InitialPos.Xpos, 0, 0)));
    double angleZ = atan(3/getDistance(min[i].getPos().Xpos, InitialPos.Xpos,min[i].getPos().Ypos,InitialPos.Ypos));

    if(CheckTimerDelay())
    {
        if(min[i].getPos().Xpos > InitialPos.Xpos + Pos.Xpos)
            Pos.Xpos += cos(angle)* stepSize;
        if(min[i].getPos().Xpos < InitialPos.Xpos + Pos.Xpos)
            Pos.Xpos -= cos(angle)* stepSize;
        if(min[i].getPos().Ypos  >  InitialPos.Ypos + Pos.Ypos)
            Pos.Ypos += sin(angle) * stepSize;
        if(min[i].getPos().Ypos  <  InitialPos.Ypos + Pos.Ypos)
            Pos.Ypos -= sin(angle) * stepSize;
        if(Zpos > -2)
            Zpos -= sin(angleZ)* stepSize;
            if((min[i].getPos() *= (Pos + InitialPos)))
    {
           return true;
    }
    }

    return false;

}


bool Bullet :: Fire(Position P)
{
    Position target = P;
    double angle = atan(getDistance(0,0,target.Ypos, InitialPos.Ypos)/(getDistance(target.Xpos, InitialPos.Xpos, 0, 0)));
    double angleZ = atan(3/getDistance(target.Xpos, InitialPos.Xpos,target.Ypos,InitialPos.Ypos));

    if(Timer.elapsedTime()>= delay)
    {
        if(target.Xpos > InitialPos.Xpos + Pos.Xpos)
            Pos.Xpos += cos(angle)* stepSize;
        if(target.Xpos < InitialPos.Xpos + Pos.Xpos)
            Pos.Xpos -= cos(angle)* stepSize;
        if(target.Ypos  >  InitialPos.Ypos + Pos.Ypos)
            Pos.Ypos += sin(angle) * stepSize;
        if(target.Ypos  <  InitialPos.Ypos + Pos.Ypos)
            Pos.Ypos -= sin(angle) * stepSize;
        if(Zpos > -2)
            Zpos -= sin(angleZ)* stepSize;
            if((target *= (Pos + InitialPos)))
    {
           return true;
    }
    }

    return false;
}

void Bullet :: hitEffect(std::vector<Minion> &min, int i)
{
     min[i].changeHealth(min[i].getHealth() - bulletDamage);
            if(min[i].getHealth()<= 0)
            {
                if(min.size() != 0)
                {
                min.erase(min.begin()+i);

                //Since min.erase will change the index of ever minion in the vector
                //after the one being erased, we need to update the index of those minions.
                for(int newIndex = i; newIndex < min.size(); newIndex++)
                {
                    min[newIndex].SetIndex(newIndex);
                }

                }
            }
            Pos = Position(0,0);
            Zpos = GROUND + 2.4;
            Timer.start();


}

//Gets the distance between two arbitrary points
float Bullet :: getDistance(float X1, float X2, float Y1, float Y2)
{
    return sqrt(pow(X2 - X1, 2) + pow(Y2 - Y1, 2));
}

void Bullet :: setPos(Position P)
{
    Pos = P;
}
Position Bullet :: getPos()
{
    return Pos;
}

double Bullet :: GetRange()
{
    return range;
}
void Bullet :: SetRange(double x)
{
    range = x;
}

void Bullet ::SetBulletDamage(double amount)
{
    bulletDamage = amount;
}

Bullet::~Bullet()
{
    //dtor
}
